package com.ly.heart.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ly.common.core.domain.AjaxResult;
import com.ly.common.enums.KingCalculateType;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.erp.ConstUtil;
import com.ly.common.utils.erp.SnowflakeIdWorker;
import com.ly.heart.domain.*;
import com.ly.heart.mapper.KingCalculateMapper;
import com.ly.heart.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 金蝶，先进先出核算列表(没有期初和期末) 服务实现类
 * </p>
 *
 * @author WuZH
 * @since 2024-08-11
 */
@Service
public class KingCalculateServiceImpl extends ServiceImpl<KingCalculateMapper, KingCalculateEntity> implements IKingCalculateService {

    @Resource
    private IKingInventoryMaterialService iKingInventoryMaterialService;
    @Resource
    private IKingInventoryService iKingInventoryService;
    @Resource
    private IKingProcureRefundService kingProcureRefundService;
    @Resource
    private IKingProcureRefundMaterialService kingProcureRefundMaterialService;
    @Resource
    private IKingSaleRefundService kingSaleRefundService;
    @Resource
    private IKingSaleRefundDetailService kingSaleRefundMaterialService;
    @Resource
    private IKingProfitLossService kingProfitLossEntityService;
    @Resource
    private IKingProfitLossDetailService KingProfitLossDetailService;
    @Resource
    private IKingAssembleService kingAssembleEntityService;
    @Resource
    private IKingAssembleDetailService iKingAssembleDetailService;


    @Override
    public AjaxResult queryList (KingCalculateEntity kingCalculateEntity) {

        return AjaxResult.success ();
    }

    /**
     * 汇总没有期初和期末数据：
     * 1、页面新增《汇总》按钮；
     * 2、拉取如下已审批成功的单据：
     * 进出明细类型	        先进先出类型     出入库类型      单据	                成本来源	            现金先出批次	        备注
     * 收入	            收入	        入库	        采购入库单	            入库钩稽	            新批次
     * 收入	            发出	        出库	        采购退料单	            入库钩稽	            原批次
     * 收入	            收入	        入库	        其他入库单-普通	        手工维护（单据录入）	    新批次
     * 收入	            发出	        出库	        其他入库单-退货			                                            其他入库单不做退料
     * 收入	            收入	        入库	        盘盈单	                手工维护（单据录入）	    新批次
     * 发出	            发出	        出库	        盘亏单	                计价方法（先进先出）	    先进先出批次
     * 发出	            发出	        出库	        销售出库单	            计价方法（先进先出）	    先进先出批次
     * 发出	            收入	        入库	        销售退货单	            上游单据携带	            新批次
     * 发出	            发出	        出库	        其他出库单-普通	        计价方法（先进先出）	    先进先出批次
     * 发出	            收入	        入库	        其他出库单-退货	        上游单据携带	            新批次
     * 发出	            发出	        出库	        调拨单-出	            计价方法（先进先出）	    先进先出批次
     * 收入	            收入	        入库	        调拨单-入	            上游单据携带	            新批次
     * 收入	            收入	        入库	        组装拆卸单-组装（母）	其他存货核算	            新批次	            比重去拆分
     * 发出	            发出	        出库	        组装拆卸单-组装（子）	计价方法（先进先出）	    先进先出批次
     * 发出	            发出	        出库	        组装拆卸单-拆卸（母）	计价方法（先进先出）	    先进先出批次
     * 收入	            收入	        入库	        组装拆卸单-拆卸（子）	其他存货核算	            新批次	            比重去拆分，默认是数量
     * 成本调整单	-
     * 3、分别拿到《成本来源》为入库钩稽和手工维护（单据录入）两种类型的单据数据直接入库，其中总成本保留两位小数，单位成本保留六位小数，且平账
     * 4、上述其他所有类型的单据，均只带数量，然后通过本表计算出的
     * 5、计算规则：
     * 1、先拿上述第三条源单数据，入库数量，总成本和单位成本
     * 2、算本月的总入库数量和总入库成本
     * 3、根据本月入库成本计算单行的出库成本
     * 4、最后算本月总出库成本
     *
     * @param
     * @return
     */
    public AjaxResult saveSingle() {
        Date startDate = DateUtil.beginOfMonth(new Date());
        Date endDate = DateUtil.endOfMonth(new Date());
        List<KingCalculateEntity> commonList = this.getCommonList(startDate, endDate);
        //1、采购入库单
        processEntities(commonList, ConstUtil.KING_INVENTORY_TYPE_IN, startDate, endDate, KingCalculateType.CGRKD);
        //2、销售出库单
        processEntities(commonList, ConstUtil.KING_INVENTORY_TYPE_OUT, startDate, endDate, KingCalculateType.XSCKD);
        //3、采购退料单
        processRefundEntities(commonList, startDate, endDate, KingCalculateType.CGTLD);
        //4、销售退货单
        processRefundEntities(commonList, startDate, endDate, KingCalculateType.XSTHD);
        //5、盘盈单
        processRefundEntities(commonList, startDate, endDate, KingCalculateType.PYD);
        //6、盘亏单
        processRefundEntities(commonList, startDate, endDate, KingCalculateType.PKD);
        //7、组装拆卸单-组装(母)
        processRefundEntities(commonList, startDate, endDate, KingCalculateType.ZZCXD_ZZM);
        //8、组装拆卸单-组装(子)
        processRefundEntities(commonList, startDate, endDate, KingCalculateType.ZZCXD_ZZZ);
        //9、组装拆卸单-拆卸(母)
        processRefundEntities(commonList, startDate, endDate, KingCalculateType.ZZCXD_CXM);
        //10、组装拆卸单-拆卸(子)
        processRefundEntities(commonList, startDate, endDate, KingCalculateType.ZZCXD_CXZ);

        return AjaxResult.success();
    }

    /**
     * 拉取已审批的采购入库单/销售出库单
     *
     * @return
     */
    private List<KingCalculateEntity> getKingInventoryMaterialEntity(List<KingCalculateEntity> commonList, String type, Date startDate, Date endDate) {
        List<KingCalculateEntity> kingCalculateEntities = new ArrayList<>();
        List<KingInventoryEntity> inventoryEntities = iKingInventoryService.list(new LambdaQueryWrapper<>(KingInventoryEntity.class)
                .eq(KingInventoryEntity::getState, ConstUtil.STATE_FINISH)
                .eq(KingInventoryEntity::getType, type)
                .between(KingInventoryEntity::getInventoryTime, startDate, endDate));
        List<String> ids = inventoryEntities.stream().map(KingInventoryEntity::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(ids)) {
            List<KingInventoryMaterialEntity> list = iKingInventoryMaterialService.list(new LambdaQueryWrapper<KingInventoryMaterialEntity>().
                    in(KingInventoryMaterialEntity::getInventoryId, ids));

            List<KingCalculateEntity> commonListByType = commonList.stream()
                    .filter(item -> ConstUtil.KING_INVENTORY_TYPE_IN.equals(type) ?
                            KingCalculateType.CGRKD.getCode().equals(item.getTransactionType()) :
                            KingCalculateType.XSCKD.getCode().equals(item.getTransactionType()))
                    .collect(Collectors.toList());
            List<KingInventoryMaterialEntity> filteredList = list.stream()
                    .filter(item -> commonListByType.stream()
                            .noneMatch(commonItem -> commonItem.getSourceDetailId().equals(item.getId())))
                    .collect(Collectors.toList());
            filteredList.forEach(detail -> {
                KingCalculateEntity kingCalculateEntity = new KingCalculateEntity();
                KingInventoryEntity inventory = inventoryEntities.stream().filter(inventoryEntity -> inventoryEntity.getId().equals(detail.getInventoryId())).findFirst().get();
                if (ConstUtil.KING_INVENTORY_TYPE_IN.equals(type)) {
                    kingCalculateEntity.setPricingType("入库勾稽");
                    kingCalculateEntity.setInNum(detail.getReceiptsNum());
                } else {
                    kingCalculateEntity.setPricingType("先进先出法");
                    kingCalculateEntity.setOutNum(detail.getReceiptsNum());
                }
                kingCalculateEntity.setDocNo(inventory.getDocCode());
                kingCalculateEntity.setSourceDetailId(detail.getId());
                kingCalculateEntity.setBizDate(inventory.getInventoryTime());
                kingCalculateEntity.setVerifyDate(inventory.getExamineTime());
                kingCalculateEntity.setLineNumber(detail.getLineNumber());
                kingCalculateEntity.setWarehouseId(detail.getWarehouseId());
                kingCalculateEntity.setMaterialId(detail.getMaterialId());
                kingCalculateEntity.setBatchNumber(detail.getBatchNum());

                //入库总成本，入库单位成本计算
                kingCalculateEntity.setSourceType(detail.getSourceType());
                kingCalculateEntity.setSourceLineNumber(detail.getLineNumber());
                kingCalculateEntity.setSettlementCostDocNo(inventory.getDocCode());
                kingCalculateEntities.add(kingCalculateEntity);
            });
        }
        return kingCalculateEntities;
    }

    /**
     * 采购退料单
     *
     * @return
     */
    private List<KingCalculateEntity> getKingProcureRefundMaterialEntity(List<KingCalculateEntity> commonList, Date startDate, Date endDate) {
        List<KingCalculateEntity> kingCalculateEntities = new ArrayList<>();
        List<KingProcureRefundEntity> procureRefundEntityList = kingProcureRefundService.list(new LambdaQueryWrapper<>(KingProcureRefundEntity.class)
                .eq(KingProcureRefundEntity::getState, ConstUtil.STATE_FINISH)
                .between(KingProcureRefundEntity::getRefundTime, startDate, endDate));
        List<String> ids = procureRefundEntityList.stream().map(KingProcureRefundEntity::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(ids)) {
            List<KingProcureRefundMaterialEntity> list = kingProcureRefundMaterialService.list(new LambdaQueryWrapper<>(KingProcureRefundMaterialEntity.class)
                    .in(KingProcureRefundMaterialEntity::getRelationId, ids));
            List<KingCalculateEntity> commonListByType = commonList.stream()
                    .filter(item -> KingCalculateType.CGTLD.getCode().equals(item.getTransactionType()))
                    .collect(Collectors.toList());
            List<KingProcureRefundMaterialEntity> filteredList = list.stream()
                    .filter(item -> commonListByType.stream()
                            .noneMatch(commonItem -> commonItem.getSourceDetailId().equals(item.getId())))
                    .collect(Collectors.toList());
            filteredList.forEach(detail -> {
                KingCalculateEntity kingCalculateEntity = new KingCalculateEntity();
                KingProcureRefundEntity refundEntity = procureRefundEntityList.stream().filter(inventoryEntity -> inventoryEntity.getId().equals(detail.getRelationId())).findFirst().get();
                kingCalculateEntity.setTransactionType(KingCalculateType.CGTLD.getCode());
                kingCalculateEntity.setTransactionTypeName(KingCalculateType.CGTLD.getName());
                kingCalculateEntity.setPricingType("入库勾稽");
                kingCalculateEntity.setDocNo(refundEntity.getDocCode());
                kingCalculateEntity.setSourceDetailId(detail.getId());
                kingCalculateEntity.setBizDate(refundEntity.getRefundTime());
                kingCalculateEntity.setVerifyDate(refundEntity.getExamineTime());
                kingCalculateEntity.setLineNumber(detail.getLineNumber());
                kingCalculateEntity.setWarehouseId(detail.getWarehouseId());
                kingCalculateEntity.setMaterialId(detail.getMaterialId());
                kingCalculateEntity.setBatchNumber(detail.getBatchNum());
                kingCalculateEntity.setOutNum(detail.getRefundNum());
                //入库总成本，入库单位成本计算
                kingCalculateEntity.setSourceType(detail.getSourceType());
                kingCalculateEntity.setSourceLineNumber(detail.getLineNumber());
                kingCalculateEntity.setSettlementCostDocNo(refundEntity.getDocCode());
                kingCalculateEntities.add(kingCalculateEntity);
            });
        }
        return kingCalculateEntities;
    }

    /**
     * 销售退货单
     */
    private List<KingCalculateEntity> getKingSaleRefundMaterialEntity(List<KingCalculateEntity> commonList, Date startDate, Date endDate) {
        List<KingCalculateEntity> kingCalculateEntities = new ArrayList<>();
        List<KingSaleRefundEntity> saleRefundEntityList = kingSaleRefundService.list(new LambdaQueryWrapper<>(KingSaleRefundEntity.class)
                .eq(KingSaleRefundEntity::getState, ConstUtil.STATE_FINISH)
                .between(KingSaleRefundEntity::getReturnGoodsDate, startDate, endDate));
        List<String> ids = saleRefundEntityList.stream().map(KingSaleRefundEntity::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(ids)) {
            List<KingSaleRefundDetailEntity> list = kingSaleRefundMaterialService.list(new LambdaQueryWrapper<>(KingSaleRefundDetailEntity.class)
                    .in(KingSaleRefundDetailEntity::getRelationId, ids));

            List<KingCalculateEntity> commonListByType = commonList.stream()
                    .filter(item -> KingCalculateType.XSTHD.getCode().equals(item.getTransactionType()))
                    .collect(Collectors.toList());
            List<KingSaleRefundDetailEntity> filteredList = list.stream()
                    .filter(item -> commonListByType.stream()
                            .noneMatch(commonItem -> commonItem.getSourceDetailId().equals(item.getId())))
                    .collect(Collectors.toList());
            filteredList.forEach(detail -> {
                KingCalculateEntity kingCalculateEntity = new KingCalculateEntity();
                KingSaleRefundEntity refundEntity = saleRefundEntityList.stream().filter(inventoryEntity -> inventoryEntity.getId().equals(detail.getRelationId())).findFirst().get();
                kingCalculateEntity.setTransactionType(KingCalculateType.CGTLD.getCode());
                kingCalculateEntity.setTransactionTypeName(KingCalculateType.CGTLD.getName());
                kingCalculateEntity.setPricingType("入库勾稽");
                kingCalculateEntity.setDocNo(refundEntity.getRefundCode());
                kingCalculateEntity.setSourceDetailId(detail.getId());
                kingCalculateEntity.setBizDate(refundEntity.getReturnGoodsDate());
                kingCalculateEntity.setVerifyDate(refundEntity.getExamineTime());
                kingCalculateEntity.setLineNumber(detail.getLineNumber());
                kingCalculateEntity.setWarehouseId(detail.getWarehouseId());
                kingCalculateEntity.setMaterialId(detail.getMaterialId());
                kingCalculateEntity.setBatchNumber(detail.getBatchNum());
                kingCalculateEntity.setInNum(detail.getRefundNum());
                //入库总成本，入库单位成本计算
                kingCalculateEntity.setSourceType(detail.getSourceType());
                kingCalculateEntity.setSourceLineNumber(detail.getLineNumber());
                kingCalculateEntity.setSettlementCostDocNo(refundEntity.getRefundCode());
                kingCalculateEntities.add(kingCalculateEntity);
            });
        }
        return kingCalculateEntities;
    }

    /**
     * 组装拆卸单
     *
     * @param commonList
     * @param startDate
     * @param endDate
     * @param transactionType
     * @return
     */
    private List<KingCalculateEntity> getKingAssembleMaterialEntities(List<KingCalculateEntity> commonList, Date startDate, Date endDate, KingCalculateType transactionType) {
        List<KingCalculateEntity> kingCalculateEntities = new ArrayList<>();
        List<KingAssembleEntity> kingAssembleEntities = new ArrayList<>();
        if (transactionType.equals(KingCalculateType.ZZCXD_ZZM) || transactionType.equals(KingCalculateType.ZZCXD_ZZZ)) {//组装拆卸单-组装
            kingAssembleEntities = kingAssembleEntityService.list(new LambdaQueryWrapper<>(KingAssembleEntity.class)
                    .eq(KingAssembleEntity::getState, ConstUtil.STATE_FINISH)
                    .eq(KingAssembleEntity::getTransactionType, "Assembly")
                    .between(KingAssembleEntity::getBizTime, startDate, endDate)
            );
        } else {//组装拆卸单-拆卸
            kingAssembleEntities = kingAssembleEntityService.list(new LambdaQueryWrapper<>(KingAssembleEntity.class)
                    .eq(KingAssembleEntity::getState, ConstUtil.STATE_FINISH)
                    .eq(KingAssembleEntity::getTransactionType, "Dassembly")
                    .between(KingAssembleEntity::getBizTime, startDate, endDate));
        }

        List<String> ids = kingAssembleEntities.stream().map(KingAssembleEntity::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(ids)) {
            List<KingAssembleDetailEntity> list = new ArrayList<>();
            if (transactionType.equals(KingCalculateType.ZZCXD_ZZM) || transactionType.equals(KingCalculateType.ZZCXD_CXM)) {
                list = iKingAssembleDetailService.list(new LambdaQueryWrapper<>(KingAssembleDetailEntity.class)
                        .in(KingAssembleDetailEntity::getAssembleId, ids)
                        .eq(KingAssembleDetailEntity::getType, 1)
                );
            } else {
                list = iKingAssembleDetailService.list(new LambdaQueryWrapper<>(KingAssembleDetailEntity.class)
                        .in(KingAssembleDetailEntity::getAssembleId, ids)
                        .eq(KingAssembleDetailEntity::getType, 2)
                );
            }
            List<KingCalculateEntity> commonListByType = commonList.stream()
                    .filter(item -> transactionType.getCode().equals(item.getTransactionType()))
                    .collect(Collectors.toList());
            List<KingAssembleDetailEntity> filteredList = list.stream()
                    .filter(item -> commonListByType.stream()
                            .noneMatch(commonItem -> commonItem.getSourceDetailId().equals(item.getId())))
                    .collect(Collectors.toList());

            List<KingAssembleEntity> finalKingAssembleEntities = kingAssembleEntities;
            filteredList.forEach(detail -> {
                KingCalculateEntity kingCalculateEntity = new KingCalculateEntity();
                KingAssembleEntity kingAssembleEntity = finalKingAssembleEntities.stream().filter(assembleEntity -> assembleEntity.getId().equals(detail.getAssembleId())).findFirst().get();
                if (transactionType.equals(KingCalculateType.ZZCXD_ZZM) || transactionType.equals(KingCalculateType.ZZCXD_CXZ)) {
                    kingCalculateEntity.setPricingType("其他存货核算");
                    kingCalculateEntity.setInNum(detail.getNum());
                } else {
                    kingCalculateEntity.setPricingType("计价方法（先进先出）");
                    kingCalculateEntity.setOutNum(detail.getNum());
                }
                kingCalculateEntity.setDocNo(kingAssembleEntity.getDocTypeCode());
                kingCalculateEntity.setSourceDetailId(detail.getId());
                kingCalculateEntity.setBizDate(kingAssembleEntity.getBizTime());
                kingCalculateEntity.setVerifyDate(kingAssembleEntity.getExamineTime());
                kingCalculateEntity.setLineNumber(detail.getLineNumber());
                kingCalculateEntity.setWarehouseId(detail.getWarehouseCode());
                kingCalculateEntity.setMaterialId(detail.getMaterialCode());
                kingCalculateEntity.setBatchNumber(detail.getBatchNo());

                //入库总成本，入库单位成本计算
//                kingCalculateEntity.setSourceType(detail.getSourceType());
                kingCalculateEntity.setSourceLineNumber(detail.getLineNumber());
                kingCalculateEntity.setSettlementCostDocNo(kingAssembleEntity.getDocTypeCode());
                kingCalculateEntities.add(kingCalculateEntity);
            });
        }
        return kingCalculateEntities;
    }

    /**
     * 盘盈单，盘亏单
     */
    private List<KingCalculateEntity> processProfitLossEntities(List<KingCalculateEntity> commonList, Date startDate, Date endDate, KingCalculateType transactionType) {
        List<KingCalculateEntity> kingCalculateEntities = new ArrayList<>();
        List<KingProfitLossEntity> profitLossEntityList = new ArrayList<>();
        if (transactionType.equals(KingCalculateType.PYD)) {
            profitLossEntityList = kingProfitLossEntityService.list(new LambdaQueryWrapper<>(KingProfitLossEntity.class)
                    .eq(KingProfitLossEntity::getState, ConstUtil.STATE_FINISH)
                    .eq(KingProfitLossEntity::getType, 1)
                    .between(KingProfitLossEntity::getBizTime, startDate, endDate));
        } else {
            profitLossEntityList = kingProfitLossEntityService.list(new LambdaQueryWrapper<>(KingProfitLossEntity.class)
                    .eq(KingProfitLossEntity::getState, ConstUtil.STATE_FINISH)
                    .eq(KingProfitLossEntity::getType, 2)
                    .between(KingProfitLossEntity::getBizTime, startDate, endDate));
        }
        List<String> ids = profitLossEntityList.stream().map(KingProfitLossEntity::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(ids)) {
            List<KingProfitLossDetailEntity> list = KingProfitLossDetailService.list(new LambdaQueryWrapper<>(KingProfitLossDetailEntity.class)
                    .in(KingProfitLossDetailEntity::getRelationId, ids));
            List<KingCalculateEntity> commonListByType = commonList.stream()
                    .filter(item -> transactionType.getCode().equals(item.getTransactionType()))
                    .collect(Collectors.toList());
            List<KingProfitLossDetailEntity> filteredList = list.stream()
                    .filter(item -> commonListByType.stream()
                            .noneMatch(commonItem -> commonItem.getSourceDetailId().equals(item.getId())))
                    .collect(Collectors.toList());
            List<KingProfitLossEntity> finalProfitLossEntityList = profitLossEntityList;
            filteredList.forEach(detail -> {
                KingCalculateEntity kingCalculateEntity = new KingCalculateEntity();
                KingProfitLossEntity profitLossEntity = finalProfitLossEntityList.stream().filter(profitLoss -> profitLoss.getId().equals(detail.getRelationId())).findFirst().get();
                if (transactionType.equals(KingCalculateType.PYD)) {
                    kingCalculateEntity.setPricingType("手工维护（单据录入）");
                    kingCalculateEntity.setInNum(detail.getCheckNum());
                } else {
                    kingCalculateEntity.setPricingType("计价方法（先进先出）");
                    kingCalculateEntity.setOutNum(detail.getCheckNum());
                }
                kingCalculateEntity.setDocNo(profitLossEntity.getDocTypeCode());
                kingCalculateEntity.setSourceDetailId(detail.getId());
                kingCalculateEntity.setBizDate(profitLossEntity.getBizTime());
                kingCalculateEntity.setVerifyDate(profitLossEntity.getExamineTime());
                kingCalculateEntity.setLineNumber(detail.getLineNumber());
                kingCalculateEntity.setWarehouseId(detail.getWarehouseCode());
                kingCalculateEntity.setMaterialId(detail.getMaterialCode());
                kingCalculateEntity.setBatchNumber(detail.getBatchNum());
                //入库总成本，入库单位成本计算
//                kingCalculateEntity.setSourceType(detail.getSourceType());
                kingCalculateEntity.setSourceLineNumber(detail.getLineNumber());
                kingCalculateEntity.setSettlementCostDocNo(profitLossEntity.getDocTypeCode());
                kingCalculateEntities.add(kingCalculateEntity);
            });
        }
        return kingCalculateEntities;
    }

    /**
     * 采购入库，销售出库
     *
     * @param commonList
     * @param type
     * @param startDate
     * @param endDate
     * @param transactionType
     */
    private void processEntities(List<KingCalculateEntity> commonList, String type, Date startDate, Date endDate, KingCalculateType transactionType) {
        List<KingCalculateEntity> entities = getKingInventoryMaterialEntity(commonList, type, startDate, endDate);
        entities.forEach(calculate -> {
            fillCommonFields(calculate, transactionType);
            boolean save = this.save(calculate);
            if (!save) {
                throw new CustomException("处理 " + transactionType.getName() + " 失败！");
            }
        });
    }

    /**
     * 公共save方法
     *
     * @param commonList
     * @param startDate
     * @param endDate
     * @param type
     */
    private void processRefundEntities(List<KingCalculateEntity> commonList, Date startDate, Date endDate, KingCalculateType type) {
        switch (type) {
            case CGTLD:
                List<KingCalculateEntity> refundEntities = getKingProcureRefundMaterialEntity(commonList, startDate, endDate);
                refundEntities.forEach(calculate -> {
                    fillCommonFields(calculate, type);
                    boolean save = this.save(calculate);
                    if (!save) {
                        throw new CustomException("处理采购退料单失败！");
                    }
                });
                break;
            case XSTHD:
                List<KingCalculateEntity> saleRefundEntities = getKingSaleRefundMaterialEntity(commonList, startDate, endDate);
                saleRefundEntities.forEach(calculate -> {
                    fillCommonFields(calculate, type);
                    boolean save = this.save(calculate);
                    if (!save) {
                        throw new CustomException("处理销售退货单失败！");
                    }
                });
                break;
            case PYD:
                List<KingCalculateEntity> pydProfitLossEntities = processProfitLossEntities(commonList, startDate, endDate, type);
                pydProfitLossEntities.forEach(calculate -> {
                    fillCommonFields(calculate, type);
                    boolean save = this.save(calculate);
                    if (!save) {
                        throw new CustomException("处理盘盈单失败！");
                    }
                });
                break;
            case PKD:
                List<KingCalculateEntity> ptdProfitLossEntities = processProfitLossEntities(commonList, startDate, endDate, type);
                ptdProfitLossEntities.forEach(calculate -> {
                    fillCommonFields(calculate, type);
                    boolean save = this.save(calculate);
                    if (!save) {
                        throw new CustomException("处理盘亏单失败！");
                    }
                });
                break;
            case ZZCXD_ZZM:
                processKingAssembleMaterialEntities(type, commonList, startDate, endDate);
                break;
            case ZZCXD_ZZZ:
                processKingAssembleMaterialEntities(type, commonList, startDate, endDate);
                break;
            case ZZCXD_CXM:
                processKingAssembleMaterialEntities(type, commonList, startDate, endDate);
                break;
            case ZZCXD_CXZ:
                processKingAssembleMaterialEntities(type, commonList, startDate, endDate);
                break;
        }
    }

    /**
     * 分装组装拆卸单公共方法
     *
     * @param type
     * @param commonList
     * @param startDate
     * @param endDate
     */
    private void processKingAssembleMaterialEntities(KingCalculateType type, List<KingCalculateEntity> commonList, Date startDate, Date endDate) {
        List<KingCalculateEntity> kingAssembleMaterialEntities = getKingAssembleMaterialEntities(commonList, startDate, endDate, type);
        kingAssembleMaterialEntities.forEach(calculate -> {
            fillCommonFields(calculate, type);
            boolean save = this.save(calculate);
            String name = type.getName();
            if (!save) {
                log.error("处理组装拆卸单-组装母单失败！类型: " + name);
                throw new CustomException("处理组装拆卸单-" + name + "失败！");
            }
        });
    }

    private void fillCommonFields(KingCalculateEntity calculate, KingCalculateType transactionType) {
        calculate.setId(SnowflakeIdWorker.getInstance().nextStringId());
        calculate.setCreateDate(DateUtils.getNowDate());
        calculate.setCreateUserId(SecurityUtils.getLoginUser().getUser().getUserId());
        calculate.setTransactionType(transactionType.getCode());
        calculate.setTransactionTypeName(transactionType.getName());
        calculate.setCalculateIndex(transactionType.getDesc());
    }

    private List<KingCalculateEntity> getCommonList(Date startDate, Date endDate) {
        return this.list(new LambdaQueryWrapper<>(KingCalculateEntity.class)
                .between(KingCalculateEntity::getBizDate, startDate, endDate)
        );
    }

}
